package com.tongjie.hotelbooking.security.authentication;

import com.tongjie.hotelbooking.security.user.CurrentUserInfo;
import com.tongjie.hotelbooking.user.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.session.Session;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Map;

@Component
@Slf4j
public class AuthenticationService {

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private RememberMeServices rememberMeService;

    @Resource
    private RedisOperationsSessionRepository sessionRepository;

    public Authentication authenticate(HttpServletRequest request, HttpServletResponse response, UserDetails userDetails) {

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(userDetails, userDetails);
        authRequest.setDetails(new WebAuthenticationDetails(request));
        authRequest.setAuthenticated(false);

        try {
            Authentication authResponse = this.authenticationManager.authenticate(authRequest);
            log.info("login success: {}", authResponse.getPrincipal());
            this.deleteExistsSession(authResponse);

            SecurityContextHolder.getContext().setAuthentication(authResponse);
            request.getSession(true).setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());

            this.rememberMeService.loginSuccess(request, response, authResponse);
            return authResponse;
        } catch (Exception e) {
            this.rememberMeService.loginFail(request, response);
            log.error("login failed", e);
            return null;
        }
    }

    private void deleteExistsSession(Authentication authResponse) {
        Map sessionMap = this.sessionRepository.findByPrincipalName(authResponse.getName());
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            sessionRepository.deleteById(session.getId());
        }
    }

}
